home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume29 / zsh2.2 / part08 < prev    next >
Encoding:
Text File  |  1992-05-13  |  48.9 KB  |  2,525 lines

  1. Newsgroups: comp.sources.misc
  2. From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  3. Subject:  v29i104:  zsh2.2 - The Z shell, Part08/17
  4. Message-ID: <1992May13.160240.9562@sparky.imd.sterling.com>
  5. X-Md4-Signature: 63eafc497e16608b14e838d42c97828a
  6. Date: Wed, 13 May 1992 16:02:40 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  10. Posting-number: Volume 29, Issue 104
  11. Archive-name: zsh2.2/part08
  12. Environment: BSD
  13. Supersedes: zsh2.1: Volume 24, Issue 1-19
  14.  
  15. #!/bin/sh
  16. # this is aa.08 (part 8 of zsh2.2)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file zsh2.2/src/exec.c continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 8; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test ! -f _shar_wnt_.tmp; then
  33.     echo 'x - still skipping zsh2.2/src/exec.c'
  34. else
  35. echo 'x - continuing file zsh2.2/src/exec.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/exec.c' &&
  37. X                ptr = buf;
  38. X            }
  39. X        } else {
  40. X            *ptr++ = c;
  41. X            if (++cnt == bsiz) {
  42. X                char *pp = ncalloc(bsiz *= 2);
  43. X                
  44. X                memcpy(pp,buf,cnt);
  45. X                ptr = (buf = pp)+cnt;
  46. X            }
  47. X        }
  48. X    if (ptr != buf && ptr[-1] == '\n')
  49. X        ptr[-1] = '\0';
  50. X    else
  51. X        *ptr = '\0';
  52. X    if (cnt) addnode(ret,buf);
  53. X    fclose(fin);
  54. X    return ret;
  55. X}
  56. X
  57. X/* =(...) */
  58. X
  59. Xchar *getoutputfile(cmd) /**/
  60. Xchar *cmd;
  61. X{
  62. X#ifdef WAITPID
  63. Xint pid;
  64. X#endif
  65. Xchar *nam = gettemp(),*str;
  66. Xint tfil;
  67. XList list;
  68. X
  69. X    if (thisjob == -1)
  70. X        return NULL;
  71. X    for (str = cmd; *str && *str != Outpar; str++);
  72. X    if (!*str)
  73. X        zerr("oops.",NULL,0);
  74. X    *str = '\0';
  75. X    if (!(list = parselstring(cmd)))
  76. X        return NULL;
  77. X    permalloc();
  78. X    if (!jobtab[thisjob].filelist)
  79. X        jobtab[thisjob].filelist = newlist();
  80. X    addnode(jobtab[thisjob].filelist,ztrdup(nam));
  81. X    heapalloc();
  82. X#ifdef WAITPID
  83. X    if (pid = phork())
  84. X        {
  85. X        popheap();
  86. X        waitpid(pid,NULL,WUNTRACED);
  87. X        return nam;
  88. X        }
  89. X#else
  90. X    if (waitfork()) {
  91. X        popheap();
  92. X        return nam;
  93. X    }
  94. X#endif
  95. X    subsh = 1;
  96. X    close(1);
  97. X    entersubsh(0);
  98. X    tfil = creat(nam,0666);
  99. X    exiting = 1;
  100. X    execlist(list);
  101. X    close(1);
  102. X    exit(0); return NULL;
  103. X}
  104. X
  105. X/* get a temporary named pipe */
  106. X
  107. Xchar *namedpipe() /**/
  108. X{
  109. X#ifndef NO_FIFOS
  110. Xchar *tnam = gettemp();
  111. X
  112. X    if (mknod(tnam,0010666,0) < 0) return NULL;
  113. X    return tnam;
  114. X#else
  115. X    return NULL;
  116. X#endif
  117. X}
  118. X
  119. X/* <(...) */
  120. X
  121. Xchar *getoutproc(cmd) /**/
  122. Xchar *cmd;
  123. X{
  124. X#ifdef NO_FIFOS
  125. X    zerr("doesn't look like your system supports FIFOs.",NULL,0);
  126. X    return NULL;
  127. X#else
  128. XList list;
  129. Xint fd;
  130. Xchar *pnam,*str;
  131. X
  132. X    if (thisjob == -1)
  133. X        return NULL;
  134. X    for (str = cmd; *str && *str != Outpar; str++);
  135. X    if (!*str)
  136. X        zerr("oops.",NULL,0);
  137. X    *str = '\0';
  138. X    pnam = namedpipe();
  139. X    if (!pnam) return NULL;
  140. X    permalloc();
  141. X    if (!jobtab[thisjob].filelist)
  142. X        jobtab[thisjob].filelist = newlist();
  143. X    addnode(jobtab[thisjob].filelist,ztrdup(pnam));
  144. X    heapalloc();
  145. X    if (!(list = parselstring(cmd)))
  146. X        return NULL;
  147. X    if (phork())
  148. X        {
  149. X        popheap();
  150. X        return pnam;
  151. X        }
  152. X    entersubsh(1);
  153. X    closem();
  154. X    fd = open(pnam,O_WRONLY);
  155. X    if (fd == -1)
  156. X        {
  157. X        zerr("can't open %s: %e",pnam,errno);
  158. X        _exit(0);
  159. X        }
  160. X    redup(fd,1);
  161. X    fd = open("/dev/null",O_RDONLY);
  162. X    redup(fd,0);
  163. X    exiting = 1;
  164. X    execlist(list);
  165. X    close(1);
  166. X    _exit(0);  return NULL;
  167. X#endif
  168. X}
  169. X
  170. X/* >(...) */
  171. X
  172. Xchar *getinproc(cmd) /**/
  173. Xchar *cmd;
  174. X{
  175. X#ifdef NO_FIFOS
  176. X    zerr("doesn't look like your system supports FIFOs.",NULL,0);
  177. X    return NULL;
  178. X#else
  179. XList list;
  180. Xint pid,fd;
  181. Xchar *pnam,*str;
  182. X
  183. X    if (thisjob == -1)
  184. X        return NULL;
  185. X    for (str = cmd; *str && *str != Outpar; str++);
  186. X    if (!*str)
  187. X        zerr("oops.",NULL,0);
  188. X    *str = '\0';
  189. X    pnam = namedpipe();
  190. X    if (!pnam) return NULL;
  191. X    permalloc();
  192. X    if (!jobtab[thisjob].filelist)
  193. X        jobtab[thisjob].filelist = newlist();
  194. X    addnode(jobtab[thisjob].filelist,ztrdup(pnam));
  195. X    heapalloc();
  196. X    if (!(list = parselstring(cmd)))
  197. X        return NULL;
  198. X    if (pid = phork())
  199. X        {
  200. X        popheap();
  201. X        return pnam;
  202. X        }
  203. X    entersubsh(1);
  204. X    closem();
  205. X    fd = open(pnam,O_RDONLY);
  206. X    redup(fd,0);
  207. X    exiting = 1;
  208. X    execlist(list);
  209. X    _exit(0);  return NULL;
  210. X#endif
  211. X}
  212. X
  213. X/* > >(...) (does not use named pipes) */
  214. X
  215. Xint getinpipe(cmd) /**/
  216. Xchar *cmd;
  217. X{
  218. XList list;
  219. Xint pipes[2];
  220. Xchar *str = cmd;
  221. X
  222. X    for (str = cmd; *str && *str != Outpar; str++);
  223. X    if (!*str)
  224. X        zerr("oops.",NULL,0);
  225. X    *str = '\0';
  226. X    if (!(list = parselstring(cmd+2)))
  227. X        return -1;
  228. X    mpipe(pipes);
  229. X    if (phork())
  230. X        {
  231. X        popheap();
  232. X        close(pipes[1]);
  233. X        return pipes[0];
  234. X        }
  235. X    close(pipes[0]);
  236. X    closem();
  237. X    entersubsh(1);
  238. X    redup(pipes[1],1);
  239. X    exiting = 1;
  240. X    execlist(list);
  241. X    _exit(0);  return 0;
  242. X}
  243. X
  244. X/* < <(...) */
  245. X
  246. Xint getoutpipe(cmd) /**/
  247. Xchar *cmd;
  248. X{
  249. XList list;
  250. Xint pipes[2];
  251. Xchar *str;
  252. X
  253. X    for (str = cmd; *str && *str != Outpar; str++);
  254. X    if (!*str)
  255. X        zerr("oops.",NULL,0);
  256. X    *str = '\0';
  257. X    if (!(list = parselstring(cmd+2)))
  258. X        return -1;
  259. X    strinend();
  260. X    mpipe(pipes);
  261. X    if (phork())
  262. X        {
  263. X        popheap();
  264. X        close(pipes[0]);
  265. X        return pipes[1];
  266. X        }
  267. X    close(pipes[1]);
  268. X    closem();
  269. X    entersubsh(1);
  270. X    redup(pipes[0],0);
  271. X    exiting = 1;
  272. X    execlist(list);
  273. X    _exit(0);  return 0;
  274. X}
  275. X
  276. X/* run a list, saving the current job num */
  277. X
  278. Xvoid runlist(l) /**/
  279. XList l;
  280. X{
  281. Xint cj = thisjob;
  282. X
  283. X    execlist(l);
  284. X    thisjob = cj;
  285. X}
  286. X
  287. Xchar *gettemp() /**/
  288. X{
  289. X    return mktemp(dyncat(tmpprefix,"XXXXXX"));
  290. X}
  291. X
  292. X/* my getwd; all the other ones I tried confused the SIGCHLD handler */
  293. X
  294. Xchar *zgetwd() /**/
  295. X{
  296. Xstatic char buf0[MAXPATHLEN];
  297. Xchar buf3[MAXPATHLEN],*buf2 = buf0+1;
  298. Xstruct stat sbuf;
  299. Xstruct direct *de;
  300. XDIR *dir;
  301. Xino_t ino = -1;
  302. Xdev_t dev = -1;
  303. X
  304. X    holdintr();
  305. X    buf2[0] = '\0';
  306. X    buf0[0] = '/';
  307. X    for(;;)
  308. X        {
  309. X        if (stat(".",&sbuf) < 0)
  310. X            {
  311. X            chdir(buf0);
  312. X            noholdintr();
  313. X            return ztrdup(".");
  314. X            }
  315. X        ino = sbuf.st_ino;
  316. X        dev = sbuf.st_dev;
  317. X        if (stat("..",&sbuf) < 0)
  318. X            {
  319. X            chdir(buf0);
  320. X            noholdintr();
  321. X            return ztrdup(".");
  322. X            }
  323. X        if (sbuf.st_ino == ino && sbuf.st_dev == dev)
  324. X            {
  325. X            chdir(buf0);
  326. X            noholdintr();
  327. X            return ztrdup(buf0);
  328. X            }
  329. X        dir = opendir("..");
  330. X        if (!dir)
  331. X            {
  332. X            chdir(buf0);
  333. X            noholdintr();
  334. X            return ztrdup(".");
  335. X            }
  336. X        chdir("..");
  337. X        readdir(dir); readdir(dir);
  338. X        while (de = readdir(dir))
  339. X            if (de->d_ino == ino)
  340. X                {
  341. X                lstat(de->d_name,&sbuf);
  342. X                if (sbuf.st_dev == dev)
  343. X                    goto match;
  344. X                }
  345. X        rewinddir(dir);
  346. X        readdir(dir); readdir(dir);
  347. X        while (de = readdir(dir))
  348. X            {
  349. X            lstat(de->d_name,&sbuf);
  350. X            if (sbuf.st_dev == dev)
  351. X                goto match;
  352. X            }
  353. X        noholdintr();
  354. X        closedir(dir);
  355. X        return ztrdup(".");
  356. Xmatch:
  357. X        strcpy(buf3,de->d_name);
  358. X        if (*buf2)
  359. X            strcat(buf3,"/");
  360. X        strcat(buf3,buf2);
  361. X        strcpy(buf2,buf3);
  362. X        closedir(dir);
  363. X        }
  364. X}
  365. X
  366. X/* open pipes with fds >= 10 */
  367. X
  368. Xvoid mpipe(pp) /**/
  369. Xint *pp;
  370. X{
  371. X    pipe(pp);
  372. X    pp[0] = movefd(pp[0]);
  373. X    pp[1] = movefd(pp[1]);
  374. X}
  375. X
  376. X/* do process substitution with redirection */
  377. X
  378. Xvoid spawnpipes(l) /**/
  379. XLklist l;
  380. X{
  381. XLknode n = firstnode(l);
  382. XRedir f;
  383. X
  384. X    for (; n; incnode(n))
  385. X        {
  386. X        f = (Redir) getdata(n);
  387. X        if (f->type == OUTPIPE)
  388. X            {
  389. X            char *str = f->name;
  390. X            f->fd2 = getoutpipe(str);
  391. X            }
  392. X        if (f->type == INPIPE)
  393. X            {
  394. X            char *str = f->name;
  395. X            f->fd2 = getinpipe(str);
  396. X            }
  397. X        }
  398. X}
  399. X
  400. X/* perform time ... command */
  401. X
  402. Xint exectime(cmd) /**/
  403. XCmd cmd;
  404. X{
  405. Xint jb = thisjob;
  406. X
  407. X    if (!cmd->u.pline) { shelltime(); return 0; }
  408. X    execpline(cmd->u.pline,TIMED,0);
  409. X    thisjob = jb;
  410. X    return lastval;
  411. X}
  412. X
  413. X/* define a function */
  414. X
  415. Xint execfuncdef(cmd) /**/
  416. XCmd cmd;
  417. X{
  418. XCmdnam cc;
  419. Xchar *s;
  420. X
  421. X    permalloc();
  422. X    while (s = ugetnode(cmd->args))
  423. X        {
  424. X        cc = (Cmdnam) zalloc(sizeof *cc);
  425. X        cc->type = SHFUNC;
  426. X        cc->flags = 0;
  427. X        if (!cmd->u.list)
  428. X            cc->u.list = NULL;
  429. X        else
  430. X            cc->u.list = (List) dupstruct(cmd->u.list);
  431. X        addhnode(ztrdup(s),cc,cmdnamtab,freecmdnam);
  432. X        if (!strncmp(s,"TRAP",4))
  433. X            {
  434. X            int t0 = getsignum(s+4);
  435. X
  436. X            if (t0 != -1)
  437. X                settrap(t0,cmd->u.list);
  438. X            }
  439. X        }
  440. X    heapalloc();
  441. X    return 0;
  442. X}
  443. X
  444. X/* evaluate a [[ ... ]] */
  445. X
  446. Xint execcond(cmd) /**/
  447. XCmd cmd;
  448. X{
  449. X    return !evalcond(cmd->u.cond);
  450. X}
  451. X
  452. Xvoid execshfunc(cmd,cn) /**/
  453. XCmd cmd;Cmdnam cn;
  454. X{
  455. XList l;
  456. X
  457. X    if (errflag) return;
  458. X    l = cn->u.list;
  459. X    if (!l) {
  460. X        char *nam;
  461. X
  462. X        if (!(cn->flags & PMFLAG_u)) return;
  463. X        if (!(l = getfpfunc(nam = peekfirst(cmd->args)))) {
  464. X            zerr("function not found: %s",nam,0);
  465. X            lastval = 1;
  466. X            return;
  467. X        }
  468. X        cn->flags &= ~PMFLAG_u;
  469. X        permalloc();
  470. X        cn->u.list = (List) dupstruct(l);
  471. X        heapalloc();
  472. X    }
  473. X    doshfunc(l,cmd->args,cn->flags);
  474. X}
  475. X
  476. Xvoid doshfuncnoval(list,args,flags) /**/
  477. XList list; Lklist args; int flags;
  478. X{
  479. Xint val = lastval;
  480. X
  481. X    doshfunc(list,args,flags);
  482. X    lastval = val;
  483. X}
  484. X
  485. Xvoid doshfunc(list,args,flags) /**/
  486. XList list; Lklist args; int flags;
  487. X{
  488. Xchar **tab,**x,*oargv0;
  489. Xint oxtr = opts[XTRACE],opev = opts[PRINTEXITVALUE],xexittr;
  490. XLklist olist;
  491. Xchar *s;
  492. XList xexitfn;
  493. X
  494. X    xexittr = sigtrapped[SIGEXIT];
  495. X    xexitfn = sigfuncs[SIGEXIT];
  496. X    tab = pparams;
  497. X    oargv0 = argzero;
  498. X    zoptind = 1;
  499. X    if (flags & PMFLAG_t) opts[XTRACE] = OPT_SET;
  500. X    opts[PRINTEXITVALUE] = OPT_UNSET;
  501. X    if (args) {
  502. X        pparams = x = (char **) zcalloc(((sizeof *x)*(1+countnodes(args))));
  503. X        argzero = ztrdup(ugetnode(args));
  504. X        while (*x = ugetnode(args))
  505. X            *x = ztrdup(*x), x++;
  506. X    } else {
  507. X        pparams = zcalloc(sizeof *pparams);
  508. X        argzero = ztrdup(argzero);
  509. X    }
  510. X    permalloc();
  511. X    olist = locallist;
  512. X    locallist = newlist();
  513. X    heapalloc();
  514. X    runlist(dupstruct(list));
  515. X    while (s = getnode(locallist)) unsetparam(s);
  516. X    free(locallist);
  517. X    locallist = olist;
  518. X    retflag = 0;
  519. X    freearray(pparams);
  520. X    free(argzero);
  521. X    argzero = oargv0;
  522. X    pparams = tab;
  523. X    if (sigfuncs[SIGEXIT] && sigfuncs[SIGEXIT] != xexitfn) {
  524. X        dotrap(SIGEXIT);
  525. X        freestruct(sigfuncs[SIGEXIT]);
  526. X    }
  527. X    sigtrapped[SIGEXIT] = xexittr;
  528. X    sigfuncs[SIGEXIT] = xexitfn;
  529. X    opts[XTRACE] = oxtr;
  530. X    opts[PRINTEXITVALUE] = opev;
  531. X}
  532. X
  533. X/* search fpath for an undefined function */
  534. X
  535. XList getfpfunc(s) /**/
  536. Xchar *s;
  537. X{
  538. Xchar **pp = fpath,buf[MAXPATHLEN];
  539. Xint fd;
  540. X
  541. X    for (; *pp; pp++)
  542. X        {
  543. X        sprintf(buf,"%s/%s",*pp,s);
  544. X        if (!access(buf,R_OK) && (fd = open(buf,O_RDONLY)) != -1)
  545. X            {
  546. X            int len = lseek(fd,0,2);
  547. X
  548. X            if (len == -1)
  549. X                close(fd);
  550. X            else
  551. X                {
  552. X                char *d;
  553. X
  554. X                lseek(fd,0,0);
  555. X                d = zcalloc(len+1);
  556. X                if (read(fd,d,len) != len)
  557. X                    {
  558. X                    free(d);
  559. X                    close(fd);
  560. X                    }
  561. X                else
  562. X                    {
  563. X                    close(fd);
  564. X                    return parselstring(d);
  565. X                    }
  566. X                }
  567. X            }
  568. X        }
  569. X    return NULL;
  570. X}
  571. X
  572. X/* check to see if AUTOCD applies here */
  573. X
  574. Xint cancd(s)
  575. Xchar *s;
  576. X{
  577. Xchar *t;
  578. X
  579. X    if ((t = getsparam(s)) && *t == '/') return 1;
  580. X    if (*s != '/')
  581. X        {
  582. X        char sbuf[MAXPATHLEN],**cp;
  583. X
  584. X        if (cancd2(s))
  585. X            return 1;
  586. X        if (access(s,X_OK) == 0)
  587. X            return 0;
  588. X        for (cp = cdpath; *cp; cp++)
  589. X            {
  590. X            sprintf(sbuf,"%s/%s",*cp,s);
  591. X            if (cancd2(sbuf))
  592. X                return 1;
  593. X            }
  594. X        return 0;
  595. X        }
  596. X    return cancd2(s);
  597. X}
  598. X
  599. Xint cancd2(s)
  600. Xchar *s;
  601. X{
  602. Xstruct stat buf;
  603. X
  604. X    return !(access(s,X_OK) || stat(s,&buf) || !S_ISDIR(buf.st_mode));
  605. X}
  606. X
  607. SHAR_EOF
  608. echo 'File zsh2.2/src/exec.c is complete' &&
  609. chmod 0644 zsh2.2/src/exec.c ||
  610. echo 'restore of zsh2.2/src/exec.c failed'
  611. Wc_c="`wc -c < 'zsh2.2/src/exec.c'`"
  612. test 35818 -eq "$Wc_c" ||
  613.     echo 'zsh2.2/src/exec.c: original size 35818, current size' "$Wc_c"
  614. rm -f _shar_wnt_.tmp
  615. fi
  616. # ============= zsh2.2/src/funcs.h ==============
  617. if test -f 'zsh2.2/src/funcs.h' -a X"$1" != X"-c"; then
  618.     echo 'x - skipping zsh2.2/src/funcs.h (File already exists)'
  619.     rm -f _shar_wnt_.tmp
  620. else
  621. > _shar_wnt_.tmp
  622. echo 'x - extracting zsh2.2/src/funcs.h (Text)'
  623. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/funcs.h' &&
  624. Xstruct asgment;
  625. Xstruct utmp;
  626. X
  627. X#include "builtin.pro"
  628. X#include "cond.pro"
  629. X#include "exec.pro"
  630. X#include "glob.pro"
  631. X#include "hist.pro"
  632. X#include "init.pro"
  633. X#include "jobs.pro"
  634. X#include "lex.pro"
  635. X#include "loop.pro"
  636. X#include "math.pro"
  637. X#include "mem.pro"
  638. X#include "params.pro"
  639. X#include "parse.pro"
  640. X#include "subst.pro"
  641. X#include "table.pro"
  642. X#include "text.pro"
  643. X#include "utils.pro"
  644. X#include "watch.pro"
  645. X#include "zle_hist.pro"
  646. X#include "zle_main.pro"
  647. X#include "zle_misc.pro"
  648. X#include "zle_move.pro"
  649. X#include "zle_refresh.pro"
  650. X#include "zle_tricky.pro"
  651. X#include "zle_utils.pro"
  652. X#include "zle_vi.pro"
  653. X#include "zle_word.pro"
  654. X
  655. Xchar *mktemp DCLPROTO((char *));
  656. X#ifndef HAS_STDLIB
  657. Xchar *malloc DCLPROTO((int));
  658. Xchar *realloc DCLPROTO((char *,int));
  659. Xchar *calloc DCLPROTO((int,int));
  660. X#endif
  661. Xchar *ttyname DCLPROTO((int));
  662. X
  663. Xextern char PC, *BC, *UP;
  664. Xextern short ospeed;
  665. Xextern int tgetent DCLPROTO((char *bp, char *name));
  666. Xextern int tgetnum DCLPROTO((char *id));
  667. Xextern int tgetflag DCLPROTO((char *id));
  668. Xextern char *tgetstr DCLPROTO((char *id, char **area));
  669. Xextern char *tgoto DCLPROTO((char *cm, int destcol, int destline));
  670. Xextern int tputs DCLPROTO((char *cp, int affcnt, int (*outc)()));
  671. SHAR_EOF
  672. chmod 0644 zsh2.2/src/funcs.h ||
  673. echo 'restore of zsh2.2/src/funcs.h failed'
  674. Wc_c="`wc -c < 'zsh2.2/src/funcs.h'`"
  675. test 1185 -eq "$Wc_c" ||
  676.     echo 'zsh2.2/src/funcs.h: original size 1185, current size' "$Wc_c"
  677. rm -f _shar_wnt_.tmp
  678. fi
  679. # ============= zsh2.2/src/glob.c ==============
  680. if test -f 'zsh2.2/src/glob.c' -a X"$1" != X"-c"; then
  681.     echo 'x - skipping zsh2.2/src/glob.c (File already exists)'
  682.     rm -f _shar_wnt_.tmp
  683. else
  684. > _shar_wnt_.tmp
  685. echo 'x - extracting zsh2.2/src/glob.c (Text)'
  686. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/glob.c' &&
  687. X/*
  688. X *
  689. X * glob.c - filename generation
  690. X *
  691. X * This file is part of zsh, the Z shell.
  692. X *
  693. X * This software is Copyright 1992 by Paul Falstad
  694. X *
  695. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  696. X * use this software as long as: there is no monetary profit gained
  697. X * specifically from the use or reproduction of this software, it is not
  698. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  699. X * included prominently in any copy made. 
  700. X *
  701. X * The author make no claims as to the fitness or correctness of this software
  702. X * for any use whatsoever, and it is provided as is. Any use of this software
  703. X * is at the user's own risk. 
  704. X *
  705. X */
  706. X
  707. X#include "zsh.h"
  708. X
  709. X#ifdef __hpux
  710. X#include <ndir.h>
  711. X#else
  712. X#ifdef SYSV
  713. X#define direct dirent
  714. X#else
  715. X#include <sys/dir.h>
  716. X#endif
  717. X#endif
  718. X#include <sys/errno.h>
  719. X
  720. X#define exists(X) (access(X,0) == 0 || readlink(X,NULL,0) == 0)
  721. X
  722. Xstatic int mode;                /* != 0 if we are parsing glob patterns */
  723. Xstatic int pathpos;            /* position in pathbuf */
  724. Xstatic int matchsz;            /* size of matchbuf */
  725. Xstatic int matchct;            /* number of matches found */
  726. Xstatic char pathbuf[MAXPATHLEN];    /* pathname buffer */
  727. Xstatic char **matchbuf;        /* array of matches */
  728. Xstatic char **matchptr;        /* &matchbuf[matchct] */
  729. Xstatic Comp exclude;            /* pattern to exclude */
  730. X
  731. X/* max # of qualifiers */
  732. X
  733. X#define QUALCT 16
  734. X
  735. Xstatic int (*qualfuncs[QUALCT])DCLPROTO((struct stat *,long));
  736. Xstatic long qualdata[QUALCT];
  737. Xstatic int qualsense[QUALCT];
  738. Xstatic int qualct;
  739. Xstatic int gf_nullglob,gf_markdirs,gf_noglobdots;
  740. X
  741. X/* pathname component in filename patterns */
  742. X
  743. Xstruct complist {
  744. X    Complist next;
  745. X    Comp comp;
  746. X    int closure;    /* 1 if this is a (foo/)# */
  747. X    };
  748. Xstruct comp {
  749. X    Comp left,right,next;
  750. X    char *str;
  751. X    int closure,last;
  752. X    };
  753. X
  754. Xvoid glob(list,np) /**/
  755. XLklist list;Lknode *np;
  756. X{
  757. XLknode node = prevnode(*np);
  758. XLknode next = nextnode(*np);
  759. Xint sl;            /* length of the pattern */
  760. Xchar *ostr;        /* the pattern before the parser chops it up */
  761. XComplist q;        /* pattern after parsing */
  762. Xchar *str = getdata(*np);    /* the pattern */
  763. X
  764. X    sl = strlen(str);
  765. X    ostr = strdup(str);
  766. X    uremnode(list,*np);
  767. X    qualct = 0;
  768. X    gf_nullglob = isset(NULLGLOB);
  769. X    gf_markdirs = isset(MARKDIRS);
  770. X    gf_noglobdots = unset(GLOBDOTS);
  771. X    if (str[sl-1] == Outpar)    /* check for qualifiers */
  772. X        {
  773. X        char *s;
  774. X        int sense = 0;
  775. X        long data;
  776. X        int (*func) DCLPROTO((struct stat *,long));
  777. X
  778. X        for (s = str+sl-2; s != str; s--)
  779. X            if (*s == Bar || *s == Outpar || *s == Inpar)
  780. X                break;
  781. X        if (*s == Inpar)
  782. X            {
  783. X            *s++ = '\0';
  784. X            func = NULL;
  785. X            while (*s != Outpar)
  786. X                {
  787. X                func = NULL;
  788. X                if (idigit(*s))
  789. X                    {
  790. X                    func = qualflags;
  791. X                    data = 0;
  792. X                    while (idigit(*s))
  793. X                        data = data*010+(*s++-'0');
  794. X                    }
  795. X                else switch ((int)(unsigned char)(*s++))
  796. X                    {
  797. X                    case (int)(unsigned char)Hat: case '^': sense = 1-sense; break;
  798. X#ifdef S_IFLNK
  799. X                    case '@': func = qualmode; data = S_IFLNK; break;
  800. X#endif
  801. X#ifdef S_IFSOCK
  802. X                    case '=': func = qualmode; data = S_IFSOCK; break;
  803. X#endif
  804. X#ifdef S_IFIFO
  805. X                    case 'p': func = qualmode; data = S_IFIFO; break;
  806. X#endif
  807. X                    case '/': func = qualmode; data = S_IFDIR; break;
  808. X                    case '.': func = qualmode; data = S_IFREG; break;
  809. X                    case '%': func = qualisdev; break;
  810. X                    case (int)(unsigned char)Star:  func = qualiscom; break;
  811. X                    case 'R': func = qualflags; data = 0004; break;
  812. X                    case 'W': func = qualflags; data = 0002; break;
  813. X                    case 'X': func = qualflags; data = 0001; break;
  814. X                    case 'r': func = qualflags; data = 0400; break;
  815. X                    case 'w': func = qualflags; data = 0200; break;
  816. X                    case 'x': func = qualflags; data = 0100; break;
  817. X                    case 's': func = qualflags; data = 04000; break;
  818. X                    case 'S': func = qualflags; data = 02000; break;
  819. X                    case 'd': func = qualdev; data = qgetnum(&s); break;
  820. X                    case 'l': func = qualnlink; data = qgetnum(&s); break;
  821. X                    case 'U': func = qualuid; data = geteuid(); break;
  822. X                    case 'G': func = qualgid; data = getegid(); break;
  823. X                    case 'u': func = qualuid; data = qgetnum(&s); break;
  824. X                    case 'g': func = qualgid; data = qgetnum(&s); break;
  825. X                    case 'M': gf_markdirs = !sense; break;
  826. X                    case 'N': gf_nullglob = !sense; break;
  827. X                    case 'D': gf_noglobdots = sense; break;
  828. X                    default: zerr("unknown file attribute",NULL,0); return;
  829. X                    }
  830. X                if (func)
  831. X                    {
  832. X                    if (qualct == QUALCT-1)
  833. X                        {
  834. X                        zerr("too many qualifiers",NULL,0);
  835. X                        return;
  836. X                        }
  837. X                    qualfuncs[qualct] = func;
  838. X                    qualsense[qualct] = sense;
  839. X                    qualdata[qualct] = data;
  840. X                    qualct++;
  841. X                    }
  842. X                if (errflag)
  843. X                    return;
  844. X                }
  845. X            }
  846. X        }
  847. X    else if ((str[sl-1] == '/') && !((str[sl-2] == Star)&&
  848. X                (str[sl-3] == Star)&&(str[sl-4] == Star)&&
  849. X                (str[sl-5]==Star)))        /* foo/ == foo(/) */
  850. X        {
  851. X        str[sl-1] = '\0';
  852. X        qualfuncs[0] = qualmode;
  853. X        qualdata[0] = S_IFDIR;
  854. X        qualsense[0] = 0;
  855. X        qualct = 1;
  856. X        }
  857. X    qualfuncs[qualct] = NULL;
  858. X    if (*str == '/')    /* pattern has absolute path */
  859. X        {
  860. X        str++;
  861. X        pathbuf[0] = '/';
  862. X        pathbuf[pathpos = 1] = '\0';
  863. X        }
  864. X    else        /* pattern is relative to pwd */
  865. X        pathbuf[pathpos = 0] = '\0';
  866. X    q = parsepat(str);
  867. X    if (!q || errflag)    /* if parsing failed */
  868. X        {
  869. X        if (isset(NOBADPATTERN))
  870. X            {
  871. X            insnode(list,node,ostr);
  872. X            return;
  873. X            }
  874. X        errflag = 0;
  875. X        zerr("bad pattern: %s",ostr,0);
  876. X        return;
  877. X        }
  878. X    matchptr = matchbuf = (char **) zalloc((matchsz = 16)*sizeof(char *));
  879. X    matchct = 0;
  880. X    scanner(q);        /* do the globbing */
  881. X    if (matchct)
  882. X        badcshglob |= 2;
  883. X    else if (!gf_nullglob)
  884. X        if (isset(CSHNULLGLOB)) {
  885. X            badcshglob |= 1;
  886. X        } else if (unset(NONOMATCH)) {
  887. X            zerr("no matches found: %s",ostr,0);
  888. X            free(matchbuf);
  889. X            return;
  890. X        } else {
  891. X            *matchptr++ = strdup(ostr);
  892. X            matchct = 1;
  893. X        }
  894. X    qsort(&matchbuf[0],matchct,sizeof(char *),notstrcmp);
  895. X    matchptr = matchbuf;
  896. X    while (matchct--)            /* insert matches in the arg list */
  897. X        insnode(list,node,*matchptr++);
  898. X    free(matchbuf);
  899. X    *np = (next) ? prevnode(next) : lastnode(list);
  900. X}
  901. X
  902. X/* get number after qualifier */
  903. X
  904. Xlong qgetnum(s) /**/
  905. Xchar **s;
  906. X{
  907. Xlong v = 0;
  908. X
  909. X    if (!idigit(**s))
  910. X        {
  911. X        zerr("number expected",NULL,0);
  912. X        return 0;
  913. X        }
  914. X    while (idigit(**s))
  915. X        v = v*10+*(*s)++-'0';
  916. X    return v;
  917. X}
  918. X
  919. Xint notstrcmp(a,b) /**/
  920. Xchar **a;char **b;
  921. X{
  922. Xchar *c = *b,*d = *a;
  923. Xint x1,x2;
  924. X
  925. X    for (; *c == *d && *c; c++,d++);
  926. X    x1 = atoi(c); x2 = atoi(d);
  927. X    if (x1==x2 || unset(NUMERICGLOBSORT))
  928. X        return ((int) (unsigned char) *c-(int) (unsigned char) *d);
  929. X    return x1-x2;
  930. X}
  931. X
  932. Xint forstrcmp(a,b) /**/
  933. Xchar **a;char **b;
  934. X{
  935. Xchar *c = *b,*d = *a;
  936. X
  937. X    for (; *c == *d && *c; c++,d++);
  938. X    return ((int) (unsigned char) *d-(int) (unsigned char) *c);
  939. X}
  940. X
  941. X/* add a match to the list */
  942. X
  943. Xvoid insert(s) /**/
  944. Xchar *s;
  945. X{
  946. Xstruct stat buf;
  947. Xint statted = 0;
  948. X
  949. X    if (exclude && domatch(s,exclude,gf_noglobdots)) return;
  950. X    if (gf_markdirs && !lstat(s,&buf) && S_ISDIR(buf.st_mode)) {
  951. X        char *t;
  952. X        int ll = strlen(s);
  953. X
  954. X        t = ncalloc(ll+2);
  955. X        strcpy(t,s);
  956. X        t[ll] = '/';
  957. X        t[ll+1] = '\0';
  958. X        s = t;
  959. X        statted = 1;
  960. X    }
  961. X    if (qualct)    { /* do the (X) (^X) stuff */
  962. X        int (**fptr)DCLPROTO((struct stat *,long)) = qualfuncs;
  963. X        int *sptr = qualsense;
  964. X        long *lptr = qualdata;
  965. X        struct stat buf;
  966. X
  967. X        if (statted || lstat(s,&buf) >= 0)
  968. X            while (*fptr) if (!(!!((*fptr++)(&buf,*lptr++)) ^ *sptr++)) return;
  969. X    }
  970. X    *matchptr++ = s;
  971. X    if (++matchct == matchsz) {
  972. X        matchbuf = (char **) realloc((char *) matchbuf,
  973. X            sizeof(char **)*(matchsz *= 2));
  974. X        matchptr = matchbuf+matchct;
  975. X    }
  976. X}
  977. X
  978. X/* check to see if str is eligible for filename generation */
  979. X
  980. Xint haswilds(str) /**/
  981. Xchar *str;
  982. X{
  983. X    if ((*str == Inbrack || *str == Outbrack) && !str[1]) return 0;
  984. X    if (str[0] == '%') return 0;
  985. X    for (; *str; str++)
  986. X        if (*str == Pound || *str == Hat || *str == Star ||
  987. X                *str == Bar || *str == Inbrack || *str == Inang ||
  988. X                *str == Quest) return 1;
  989. X    return 0;
  990. X}
  991. X
  992. X/* check to see if str is eligible for brace expansion */
  993. X
  994. Xint hasbraces(str) /**/
  995. Xchar *str;
  996. X{
  997. Xint mb,bc,cmct1,cmct2;
  998. Xchar *lbr = NULL;
  999. X
  1000. X    if (str[0] == Inbrace && str[1] == Outbrace)
  1001. X        return 0;
  1002. X    if (isset(BRACECCL)) {
  1003. X        for (mb = bc = 0; *str; ++str)
  1004. X            if (*str == Inbrace) {
  1005. X                if (++bc > mb)
  1006. X                    mb = bc;
  1007. X            }
  1008. X            else if (*str == Outbrace)
  1009. X                if (--bc < 0)
  1010. X                    return(0);
  1011. X        return(mb && bc == 0);
  1012. X    }
  1013. X    for (mb = bc = cmct1 = cmct2 = 0; *str; str++)
  1014. X        {
  1015. X        if (*str == Inbrace)
  1016. X            {
  1017. X            if (!bc)
  1018. X                lbr = str;
  1019. X            bc++;
  1020. X            if (str[4] == Outbrace && str[2] == '-') /* {a-z} */
  1021. X                {
  1022. X                cmct1++;
  1023. X                if (bc == 1)
  1024. X                    cmct2++;
  1025. X                }
  1026. X            }
  1027. X        else if (*str == Outbrace)
  1028. X            {
  1029. X            bc--;
  1030. X            if (!bc)
  1031. X                {
  1032. X                if (!cmct2)
  1033. X                    {
  1034. X                    *lbr = '{';
  1035. X                    *str = '}';
  1036. X                    }
  1037. X                cmct2 = 0;
  1038. X                }
  1039. X            }
  1040. X        else if (*str == Comma && bc)
  1041. X            {
  1042. X            cmct1++;
  1043. X            if (bc == 1)
  1044. X                cmct2++;
  1045. X            }
  1046. X        if (bc > mb)
  1047. X            mb = bc;
  1048. X        if (bc < 0)
  1049. X            return 0;
  1050. X        }
  1051. X    return (mb && bc == 0 && cmct1);
  1052. X}
  1053. X
  1054. X/* expand stuff like >>*.c */
  1055. X
  1056. Xint xpandredir(fn,tab) /**/
  1057. Xstruct redir *fn;Lklist tab;
  1058. X{
  1059. XLklist fake;
  1060. Xchar *nam;
  1061. Xstruct redir *ff;
  1062. Xint ret = 0;
  1063. X
  1064. X    fake = newlist();
  1065. X    addnode(fake,fn->name);
  1066. X    prefork(fake);
  1067. X    if (!errflag)
  1068. X        postfork(fake,1);
  1069. X    if (errflag) return 0;
  1070. X    if (full(fake) && !nextnode(firstnode(fake))) {
  1071. X        fn->name = peekfirst(fake);
  1072. X        untokenize(fn->name);
  1073. X    } else
  1074. X        while (nam = ugetnode(fake)) {
  1075. X            ff = alloc(sizeof *ff);
  1076. X            *ff = *fn;
  1077. X            ff->name = nam;
  1078. X            addnode(tab,ff);
  1079. X            ret = 1;
  1080. X        }
  1081. X    return ret;
  1082. X}
  1083. X
  1084. X/* concatenate s1 and s2 in dynamically allocated buffer */
  1085. X
  1086. Xchar *dyncat(s1,s2) /**/
  1087. Xchar *s1;char *s2;
  1088. X{
  1089. Xchar *ptr;
  1090. X    ptr = ncalloc(strlen(s1)+strlen(s2)+1);
  1091. X    strcpy(ptr,s1);
  1092. X    strcat(ptr,s2);
  1093. X    return ptr;
  1094. X}
  1095. X
  1096. X/* concatenate s1, s2, and s3 in dynamically allocated buffer */
  1097. X
  1098. Xchar *tricat(s1,s2,s3) /**/
  1099. Xchar *s1;char *s2;char *s3;
  1100. X{
  1101. Xchar *ptr;
  1102. X
  1103. X    ptr = zalloc(strlen(s1)+strlen(s2)+strlen(s3)+1);
  1104. X    strcpy(ptr,s1);
  1105. X    strcat(ptr,s2);
  1106. X    strcat(ptr,s3);
  1107. X    return ptr;
  1108. X}
  1109. X
  1110. X/* brace expansion */
  1111. X
  1112. Xvoid xpandbraces(list,np) /**/
  1113. XLklist list;Lknode *np;
  1114. X{
  1115. XLknode node = (*np),last = prevnode(node);
  1116. Xchar *str = getdata(node),*str3 = str,*str2;
  1117. Xint prev, bc, comma;
  1118. X
  1119. X    for (; *str != Inbrace; str++);
  1120. X    for (str2 = str, bc = comma = 0; *str2; ++str2)
  1121. X        if (*str2 == Inbrace)
  1122. X            ++bc;
  1123. X        else if (*str2 == Outbrace) {
  1124. X            if (--bc == 0)
  1125. X                break;
  1126. X        }
  1127. X        else if (bc == 1 && *str2 == Comma)
  1128. X            ++comma;
  1129. X    if (!comma && !bc && isset(BRACECCL)) {            /* {a-mnop} */
  1130. X        char    ccl[256], *p;
  1131. X        unsigned char c1,c2,lastch;
  1132. X
  1133. X        uremnode(list,node);
  1134. X        memset(ccl, 0, sizeof(ccl) / sizeof(ccl[0]));
  1135. X        for (p = str + 1, lastch = 0; p < str2; ) {
  1136. X            if (itok(c1 = *p++))
  1137. X                c1 = ztokens[c1 - (unsigned char)Pound];
  1138. X            if (itok(c2 = *p))
  1139. X                c2 = ztokens[c2 - (unsigned char)Pound];
  1140. X            if (c1 == '-' && lastch && p < str2 && lastch <= c2) {
  1141. X                while (lastch < c2)
  1142. X                    ccl[lastch++] = 1;
  1143. X                lastch = 0;
  1144. X            }
  1145. X            else
  1146. X                ccl[lastch = c1] = 1;
  1147. X        }
  1148. X        strcpy(str + 1, str2 + 1);
  1149. X        for (p = ccl+255; p-- > ccl; )
  1150. X            if (*p) {
  1151. X                *str = p - ccl;
  1152. X                insnode(list, last, strdup(str3));
  1153. X            }
  1154. X        *np = nextnode(last);
  1155. X        return;
  1156. X    }
  1157. X     if (str[2] == '-' && str[4] == Outbrace)     /* {a-z} */
  1158. X        {
  1159. X        char c1,c2;
  1160. X
  1161. X        uremnode(list,node);
  1162. X        chuck(str);
  1163. X        c1 = *str;
  1164. X        chuck(str);
  1165. X        chuck(str);
  1166. X        c2 = *str;
  1167. X        chuck(str);
  1168. X        if (itok(c1))
  1169. X            c1 = ztokens[c1-Pound];
  1170. X        if (itok(c2))
  1171. X            c2 = ztokens[c2-Pound];
  1172. X        if (c1 < c2)
  1173. X            for (; c2 >= c1; c2--)    /* {a-z} */
  1174. X                {
  1175. X                *str = c2;
  1176. X                insnode(list,last,strdup(str3));
  1177. X                }
  1178. X        else
  1179. X            for (; c2 <= c1; c2++)    /* {z-a} */
  1180. X                {
  1181. X                *str = c2;
  1182. X                insnode(list,last,strdup(str3));
  1183. X                }
  1184. X        *np = nextnode(last);
  1185. X        return;
  1186. X        }
  1187. X    prev = str-str3;
  1188. X    str2 = getparen(str++);
  1189. X    if (!str2)
  1190. X        {
  1191. X        zerr("how did you get this error?",NULL,0);
  1192. X        return;
  1193. X        }
  1194. X    uremnode(list,node);
  1195. X    node = last;
  1196. X    for(;;)
  1197. X        {
  1198. X        char *zz,*str4;
  1199. X        int cnt;
  1200. X        
  1201. X        for (str4 = str, cnt = 0; cnt || *str != Comma && *str !=
  1202. X                Outbrace; str++)
  1203. X            if (*str == Inbrace)
  1204. X                cnt++;
  1205. X            else if (*str == Outbrace)
  1206. X                cnt--;
  1207. X            else if (!*str)
  1208. X                exit(10);
  1209. X        zz = zalloc(prev+(str-str4)+strlen(str2)+1);
  1210. X        ztrncpy(zz,str3,prev);
  1211. X        strncat(zz,str4,str-str4);
  1212. X        strcat(zz,str2);
  1213. X        insnode(list,node,zz);
  1214. X        incnode(node);
  1215. X        if (*str != Outbrace)
  1216. X            str++;
  1217. X        else
  1218. X            break;
  1219. X        }
  1220. X    *np = nextnode(last);
  1221. X}
  1222. X
  1223. X/* get closing paren, given pointer to opening paren */
  1224. X
  1225. Xchar *getparen(str) /**/
  1226. Xchar *str;
  1227. X{
  1228. Xint cnt = 1;
  1229. Xchar typein = *str++,typeout = typein+1;
  1230. X
  1231. X    for (; *str && cnt; str++)
  1232. X        if (*str == typein)
  1233. X            cnt++;
  1234. X        else if (*str == typeout)
  1235. X            cnt--;
  1236. X    if (!str && cnt)
  1237. X        return NULL;
  1238. X    return str;
  1239. X}
  1240. X
  1241. X/* check to see if a matches b (b is not a filename pattern) */
  1242. X
  1243. Xint matchpat(a,b) /**/
  1244. Xchar *a;char *b;
  1245. X{
  1246. XComp c;
  1247. Xint val,len;
  1248. Xchar *b2;
  1249. X
  1250. X    remnulargs(b);
  1251. X    len = strlen(b);
  1252. X    b2 = alloc(len+3);
  1253. X    strcpy(b2+1,b);
  1254. X    b2[0] = Inpar;
  1255. X    b2[len+1] = Outpar;
  1256. X    b2[len+2] = '\0';
  1257. X    c = parsereg(b2);
  1258. X    if (!c)
  1259. X        {
  1260. X        zerr("bad pattern: %s",b,0);
  1261. X        return 0;
  1262. X        }
  1263. X    val = domatch(a,c,0);
  1264. X    return val;
  1265. X}
  1266. X
  1267. X/* do the ${foo%%bar}, ${foo#bar} stuff */
  1268. X/* please do not laugh at this code. */
  1269. X
  1270. Xvoid getmatch(sp,pat,dd) /**/
  1271. Xchar **sp;char *pat;int dd;
  1272. X{
  1273. XComp c;
  1274. Xchar *t,*lng = NULL,cc,*s = *sp;
  1275. X
  1276. X    remnulargs(pat);
  1277. X    c = parsereg(pat);
  1278. X    if (!c)
  1279. X        {
  1280. X        zerr("bad pattern: %s",pat,0);
  1281. X        return;
  1282. X        }
  1283. X    if (!(dd & 2))
  1284. X        {
  1285. X        for (t = s; t==s || t[-1]; t++)
  1286. X            {
  1287. X            cc = *t;
  1288. X            *t = '\0';
  1289. X            if (domatch(s,c,0))
  1290. X                {
  1291. X                if (!(dd & 1))
  1292. X                    {
  1293. X                    *t = cc;
  1294. X                    t = strdup(t);
  1295. X                    *sp = t;
  1296. X                    return;
  1297. X                    }
  1298. X                lng = t;
  1299. X                }
  1300. X            *t = cc;
  1301. X            }
  1302. X        if (lng)
  1303. X            {
  1304. X            t = strdup(lng);
  1305. X            *sp = t;
  1306. X            return;
  1307. X            }
  1308. X        }
  1309. X    else
  1310. X        {
  1311. X        for (t = s+strlen(s); t >= s; t--)
  1312. X            {
  1313. X            if (domatch(t,c,0))
  1314. X                {
  1315. X                if (!(dd & 1))
  1316. X                    {
  1317. X                    cc = *t;
  1318. X                    *t = '\0';
  1319. X                    *sp = strdup(*sp);
  1320. X                    *t = cc;
  1321. X                    return;
  1322. X                    }
  1323. X                lng = t;
  1324. X                }
  1325. X            }
  1326. X        if (lng)
  1327. X            {
  1328. X            cc = *lng;
  1329. X            *lng = '\0';
  1330. X            *sp = strdup(*sp);
  1331. X            *lng = cc;
  1332. X            return;
  1333. X            }
  1334. X        }
  1335. X}
  1336. X
  1337. X/* add a component to pathbuf */
  1338. X
  1339. Xstatic int addpath(s)
  1340. Xchar *s;
  1341. X{
  1342. X    if (strlen(s)+pathpos >= MAXPATHLEN) return 0;
  1343. X    while (pathbuf[pathpos++] = *s++);
  1344. X    pathbuf[pathpos-1] = '/';
  1345. X    pathbuf[pathpos] = '\0';
  1346. X    return 1;
  1347. X}
  1348. X
  1349. Xchar *getfullpath(s) /**/
  1350. Xchar *s;
  1351. X{
  1352. Xstatic char buf[MAXPATHLEN];
  1353. X
  1354. X    strcpy(buf,pathbuf);
  1355. X    strcat(buf,s);
  1356. X    return buf;
  1357. X}
  1358. X
  1359. X/* do the globbing */
  1360. X
  1361. Xvoid scanner(q) /**/
  1362. XComplist q;
  1363. X{
  1364. XComp c;
  1365. Xint closure;
  1366. X
  1367. X    if (closure = q->closure)    /* (foo/)# */
  1368. X        if (q->closure == 2)        /* (foo/)## */
  1369. X            q->closure = 1;
  1370. X        else
  1371. X            scanner(q->next);
  1372. X    if (c = q->comp)
  1373. X        {
  1374. X        if (!(c->next || c->left) && !haswilds(c->str))
  1375. X            if (q->next)
  1376. X                {
  1377. X                int oppos = pathpos;
  1378. X
  1379. X                if (errflag)
  1380. X                    return;
  1381. X                if (q->closure && !strcmp(c->str,".")) return;
  1382. X                if (!addpath(c->str)) return;
  1383. X                if (!closure || exists(pathbuf))
  1384. X                    scanner((q->closure) ? q : q->next);
  1385. X                pathbuf[pathpos = oppos] = '\0';
  1386. X                }
  1387. X            else
  1388. X                {
  1389. X                char *s;
  1390. X
  1391. X                if (exists(s = getfullpath(c->str)))
  1392. X                    insert(strdup(s));
  1393. X                }
  1394. X        else
  1395. X            {
  1396. X            char *fn;
  1397. X            int dirs = !!q->next;
  1398. X            struct direct *de;
  1399. X            DIR *lock = opendir((*pathbuf) ? pathbuf : ".");
  1400. X             
  1401. X            if (lock == NULL)
  1402. X                return;
  1403. X            readdir(lock); readdir(lock);     /* skip . and .. */
  1404. X            while (de = readdir(lock))
  1405. X                {
  1406. X                if (errflag)
  1407. X                    break;
  1408. X                fn = &de->d_name[0];
  1409. X                if (domatch(fn,c,gf_noglobdots))
  1410. X                    {
  1411. X                    int oppos = pathpos;
  1412. X
  1413. X                    if (dirs)
  1414. X                        {
  1415. X                        if (closure)
  1416. X                            {
  1417. X                            int type3;
  1418. X                            struct stat buf;
  1419. X
  1420. X                             if (lstat(getfullpath(fn),&buf) == -1)
  1421. X                                {
  1422. X                                if (errno != ENOENT && errno != EINTR &&
  1423. X                                        errno != ENOTDIR)
  1424. X                                    {
  1425. X                                    zerr("%e: %s",fn,errno);
  1426. X                                    errflag = 0;
  1427. X                                    }
  1428. X                                continue;
  1429. X                                }
  1430. X                            type3 = buf.st_mode & S_IFMT;
  1431. X                            if (type3 != S_IFDIR)
  1432. X                                continue;
  1433. X                            }
  1434. X                        if (addpath(fn))
  1435. X                            scanner((q->closure) ? q : q->next); /* scan next level */
  1436. X                        pathbuf[pathpos = oppos] = '\0';
  1437. X                        }
  1438. X                    else insert(dyncat(pathbuf,fn));
  1439. X                    }
  1440. X                }
  1441. X            closedir(lock);
  1442. X            }
  1443. X        }
  1444. X    else
  1445. X        zerr("no idea how you got this error message.",NULL,0);
  1446. X}
  1447. X
  1448. X/* do the [..(foo)..] business */
  1449. X
  1450. Xint minimatch(pat,str) /**/
  1451. Xchar **pat;char **str;
  1452. X{
  1453. Xchar *pt = *pat+1,*s = *str;
  1454. X    
  1455. X    for (; *pt != Outpar; s++,pt++)
  1456. X        if ((*pt != Quest || !*s) && *pt != *s)
  1457. X            {
  1458. X            *pat = getparen(*pat)-1;
  1459. X            return 0;
  1460. X            }
  1461. X    *str = s-1;
  1462. X    return 1;
  1463. X}
  1464. X
  1465. Xstatic char *pptr;
  1466. Xstatic Comp tail = 0;
  1467. Xstatic int first;
  1468. X
  1469. Xint domatch(str,c,fist) /**/
  1470. Xchar *str;Comp c;int fist;
  1471. X{
  1472. X    pptr = str;
  1473. X    first = fist;
  1474. X    return doesmatch(c);
  1475. X}
  1476. X
  1477. X/* see if current pattern matches c */
  1478. X
  1479. Xint doesmatch(c) /**/
  1480. XComp c;
  1481. X{
  1482. Xchar *pat = c->str;
  1483. X
  1484. X    if (c->closure == 1) {
  1485. X        char *saves = pptr;
  1486. X
  1487. X        if (first && *pptr == '.') return 0;
  1488. X        if (doesmatch(c->next)) return 1;
  1489. X        pptr = saves;
  1490. X        first = 0;
  1491. X    }
  1492. X    for(;;)
  1493. X        {
  1494. X        if (!pat || !*pat)
  1495. X            {
  1496. X            char *saves;
  1497. X            int savei;
  1498. X
  1499. X            if (errflag)
  1500. X                return 0;
  1501. X            saves = pptr;
  1502. X            savei = first;
  1503. X            if (c->left || c->right)
  1504. X                if (!doesmatch(c->left))
  1505. X                    if (c->right)
  1506. X                        {
  1507. X                        pptr = saves;
  1508. X                        first = savei;
  1509. X                        if (!doesmatch(c->right))
  1510. X                            return 0;
  1511. X                        }
  1512. X                    else
  1513. X                        return 0;
  1514. X            if (c->closure)
  1515. X                return doesmatch(c);
  1516. X            if (!c->next)
  1517. X                return (!c->last || !*pptr);
  1518. X            return doesmatch(c->next);
  1519. X            }
  1520. X        if (first && *pptr == '.' && *pat != '.')
  1521. X            return 0;
  1522. X        if (*pat == Star)    /* final * is not expanded to ?#; returns success */
  1523. X            {
  1524. X            while (*pptr) pptr++;
  1525. X            return 1;
  1526. X            }
  1527. X        first = 0;
  1528. X        if (*pat == Quest && *pptr)
  1529. X            {
  1530. X            pptr++;
  1531. X            pat++;
  1532. X            continue;
  1533. X            }
  1534. X        if (*pat == Hat)
  1535. X            return 1-doesmatch(c->next);
  1536. X        if (*pat == Inbrack) {
  1537. X            if (!*pptr) break;
  1538. X            if (pat[1] == Hat || pat[1] == '^') {
  1539. X                pat[1] = Hat;
  1540. X                for (pat += 2; *pat != Outbrack && *pat; pat++)
  1541. X                    if (*pat == '-' && pat[-1] != Hat && pat[1] != Outbrack) {
  1542. X                        if (pat[-1] <= *pptr && pat[1] >= *pptr)
  1543. X                            break;
  1544. X                    } else if (*pptr == *pat) break;
  1545. X                if (!*pat) {
  1546. X                    zerr("something is very wrong.",NULL,0);
  1547. X                    return 0;
  1548. X                }
  1549. X                if (*pat != Outbrack)
  1550. X                    break;
  1551. X                pat++;
  1552. X                pptr++;
  1553. X                continue;
  1554. X            } else {
  1555. X                for (pat++; *pat != Outbrack && *pat; pat++)
  1556. X                    if (*pat == Inpar) {
  1557. X                        if (minimatch(&pat,&pptr))
  1558. X                            break;
  1559. X                    } else if (*pat == '-' && pat[-1] != Inbrack &&
  1560. X                            pat[1] != Outbrack) {
  1561. X                        if (pat[-1] <= *pptr && pat[1] >= *pptr)
  1562. X                            break;
  1563. X                    } else if (*pptr == *pat) break;
  1564. X                if (!pat || !*pat) {
  1565. X                    zerr("oh dear.  that CAN'T be right.",NULL,0);
  1566. X                    return 0;
  1567. X                }
  1568. X                if (*pat == Outbrack)
  1569. X                    break;
  1570. X                for (pptr++; *pat != Outbrack; pat++);
  1571. X                pat++;
  1572. X                continue;
  1573. X            }
  1574. X        }
  1575. X        if (*pat == Inang)
  1576. X            {
  1577. X            int t1,t2,t3;
  1578. X            char *ptr;
  1579. X
  1580. X            if (*++pat == Outang)    /* handle <> case */
  1581. X                {
  1582. X                ( void ) zstrtol(pptr,&ptr,10);
  1583. X                if (ptr == pptr)
  1584. X                    break;
  1585. X                pptr = ptr;
  1586. X                pat++;
  1587. X                }
  1588. X            else
  1589. X                {
  1590. X                t1 = zstrtol(pptr,&ptr,10);
  1591. X                if (ptr == pptr)
  1592. X                    break;
  1593. X                pptr = ptr;
  1594. X                t2 = zstrtol(pat,&ptr,10);
  1595. X                if (*ptr != '-')
  1596. X                    exit(31);
  1597. X                t3 = zstrtol(ptr+1,&pat,10);
  1598. X                if (!t3)
  1599. X                    t3 = -1;
  1600. X                if (*pat++ != Outang)
  1601. X                    exit(21);
  1602. X                if (t1 < t2 || (t3 != -1 && t1 > t3))
  1603. X                    break;
  1604. X                }
  1605. X            continue;
  1606. X            }
  1607. X        if (*pptr == *pat)
  1608. X            {
  1609. X            pptr++;
  1610. X            pat++;
  1611. X            continue;
  1612. X            }
  1613. X        break;
  1614. X        }
  1615. X    return 0;
  1616. X}
  1617. X
  1618. XComplist parsepat(str) /**/
  1619. Xchar *str;
  1620. X{
  1621. Xchar *s;
  1622. X
  1623. X    exclude = NULL;
  1624. X    if (isset(EXTENDEDGLOB)) {
  1625. X        s = str+strlen(str);
  1626. X        while (s-- > str) {
  1627. X            if (*s == Tilde && s[1]) {
  1628. X                *s++ = '\0';
  1629. X                exclude = parsereg(s);
  1630. X                if (!exclude) return NULL;
  1631. X                break;
  1632. X            }
  1633. X        }
  1634. X    }
  1635. X    mode = 0;
  1636. X    pptr = str;
  1637. X    return parsecomplist();
  1638. X}
  1639. X
  1640. XComp parsereg(str) /**/
  1641. Xchar *str;
  1642. X{
  1643. X    mode = 1;
  1644. X    pptr = str;
  1645. X    return parsecompsw();
  1646. X}
  1647. X
  1648. XComplist parsecomplist() /**/
  1649. X{
  1650. XComp c1;
  1651. XComplist p1;
  1652. X
  1653. X    if (pptr[0] == Star && pptr[1] == Star &&
  1654. X            (pptr[2] == '/' ||
  1655. X            (pptr[2] == Star && pptr[3] == Star && pptr[4] == '/'))) {
  1656. X        pptr += 3;
  1657. X        if (pptr[-1] == Star) pptr += 2;
  1658. X        p1 = (Complist) alloc(sizeof *p1);
  1659. X        p1->next = parsecomplist();
  1660. X        p1->comp = (Comp) alloc(sizeof *p1->comp);
  1661. X        p1->comp->last = 1;
  1662. X        p1->comp->str = strdup("*");
  1663. X        *p1->comp->str = Star;
  1664. X        p1->closure = 1;
  1665. X        return p1;
  1666. X    }
  1667. X    if (*pptr == Inpar)
  1668. X        {
  1669. X        char *str;
  1670. X        int pars = 1;
  1671. X
  1672. X        for (str = pptr+1; *str && pars; str++)
  1673. X            if (*str == Inpar)
  1674. X                pars++;
  1675. X            else if (*str == Outpar)
  1676. X                pars--;
  1677. X        if (str[0] != Pound || str[-1] != Outpar || str[-2] != '/')
  1678. X            goto kludge;
  1679. X        pptr++;
  1680. X        if (!(c1 = parsecompsw()))
  1681. X            return NULL;
  1682. X        if (pptr[0] == '/' && pptr[1] == Outpar && pptr[2] == Pound)
  1683. X            {
  1684. X            int pdflag = 0;
  1685. X
  1686. X            pptr += 3;
  1687. X            if (*pptr == Pound)
  1688. X                {
  1689. X                pdflag = 1;
  1690. X                pptr++;
  1691. X                }
  1692. X            p1 = (Complist) alloc(sizeof *p1);
  1693. X            p1->comp = c1;
  1694. X            p1->closure = 1+pdflag;
  1695. X            p1->next = parsecomplist();
  1696. X            return (p1->comp) ? p1 : NULL;
  1697. X            }
  1698. X        }
  1699. X    else
  1700. X        {
  1701. Xkludge:
  1702. X        if (!(c1 = parsecompsw()))
  1703. X            return NULL;
  1704. X        if (*pptr == '/' || !*pptr)
  1705. X            {
  1706. X            int ef = *pptr == '/';
  1707. X
  1708. X            p1 = (Complist) alloc(sizeof *p1);
  1709. X            p1->comp = c1;
  1710. X            p1->closure = 0;
  1711. X            p1->next = (*pptr == '/') ? (pptr++,parsecomplist()) : NULL;
  1712. X            return (ef && !p1->next) ? NULL : p1;
  1713. X            }
  1714. X        }
  1715. X    errflag = 1;
  1716. X    return NULL;
  1717. X}
  1718. X
  1719. XComp parsecomp() /**/
  1720. X{
  1721. XComp c = (Comp) alloc(sizeof *c),c1,c2;
  1722. Xchar *s = c->str = alloc(MAXPATHLEN*2),*ls = NULL;
  1723. X
  1724. X    c->next = tail;
  1725. X
  1726. X    while (*pptr && (mode || *pptr != '/') && *pptr != Bar &&
  1727. X            *pptr != Outpar)
  1728. X        {
  1729. X        if (*pptr == Hat)
  1730. X            {
  1731. X            *s++ = Hat;
  1732. X            *s++ = '\0';
  1733. X            pptr++;
  1734. X            if (!(c->next = parsecomp()))
  1735. X                return NULL;
  1736. X            return c;
  1737. X            }
  1738. X        if (*pptr == Star && pptr[1] && (mode || pptr[1] != '/'))
  1739. X            {
  1740. X            *s++ = '\0';
  1741. X            pptr++;
  1742. X            c1 = (Comp) alloc(sizeof *c1);
  1743. X            *(c1->str = strdup("?")) = Quest;
  1744. X            c1->closure = 1;
  1745. X            if (!(c2 = parsecomp())) return NULL;
  1746. X            c1->next = c2;
  1747. X            c->next = c1;
  1748. X            return c;
  1749. X            }
  1750. X        if (*pptr == Inpar)
  1751. X            {
  1752. X            int pars = 1;
  1753. X            char *startp = pptr, *endp;
  1754. X            Comp stail = tail;
  1755. X            int dpnd = 0;
  1756. X
  1757. X            for (pptr = pptr+1; *pptr && pars; pptr++)
  1758. X                if (*pptr == Inpar)
  1759. X                    pars++;
  1760. X                else if (*pptr == Outpar)
  1761. X                    pars--;
  1762. X            if (pptr[-1] != Outpar)
  1763. X                {
  1764. X                errflag = 1;
  1765. X                return NULL;
  1766. X                }
  1767. X            if (*pptr == Pound)
  1768. X                {
  1769. X                dpnd = 1;
  1770. X                pptr++;
  1771. X                if (*pptr == Pound)
  1772. X                    {
  1773. X                    pptr++;
  1774. X                    dpnd = 2;
  1775. X                    }
  1776. X                }
  1777. X            if (!(c1 = parsecomp())) return NULL;
  1778. X            tail = c1;
  1779. X            endp = pptr;
  1780. X            pptr = startp;
  1781. X            pptr++;
  1782. X            *s++ = '\0';
  1783. X            c->next = (Comp) alloc(sizeof *c);
  1784. X            c->next->left = parsecompsw();
  1785. X            c->next->closure = dpnd;
  1786. X            c->next->next = (Comp) alloc(sizeof *c);
  1787. X            pptr = endp;
  1788. X            tail = stail;
  1789. X            return c;
  1790. X            }
  1791. X        if (*pptr == Pound)
  1792. X            {
  1793. X            *s = '\0';
  1794. X            pptr++;
  1795. X            if (!ls)
  1796. X                return NULL;
  1797. X            if (*pptr == Pound) 
  1798. X                {
  1799. X                pptr++;
  1800. X                c->next = c1 = (Comp) alloc(sizeof *c);
  1801. X                c1->str = strdup(ls);
  1802. X                }
  1803. X            else
  1804. X                c1 = c;
  1805. X            c1->next = c2 = (Comp) alloc(sizeof *c);
  1806. X            c2->str = strdup(ls);
  1807. X            c2->closure = 1;
  1808. X            c2->next = parsecomp();
  1809. X            if (!c2->next)
  1810. X                return NULL;
  1811. X            *ls++ = '\0';
  1812. X            return c;
  1813. X            }
  1814. X        ls = s;
  1815. X        if (*pptr == Inang)
  1816. X            {
  1817. X            int dshct;
  1818. X
  1819. X            dshct = (pptr[1] == Outang);
  1820. X            *s++ = *pptr++;
  1821. X            while (*pptr && (*s++ = *pptr++) != Outang)
  1822. X                if (s[-1] == '-')
  1823. X                    dshct++;
  1824. X                else if (!idigit(s[-1]))
  1825. X                    break;
  1826. X            if (s[-1] != Outang || dshct != 1)
  1827. X                return NULL;
  1828. X            }
  1829. X        else if (*pptr == Inbrack)
  1830. X            {
  1831. X            while (*pptr && (*s++ = *pptr++) != Outbrack);
  1832. X            if (s[-1] != Outbrack)
  1833. X                return NULL;
  1834. X            }
  1835. X        else if (itok(*pptr) && *pptr != Star && *pptr != Quest)
  1836. X            *s++ = ztokens[*pptr++-Pound];
  1837. X        else
  1838. X            *s++ = *pptr++;
  1839. X        }
  1840. X    if (*pptr == '/' || !*pptr)
  1841. X        c->last = 1;
  1842. X    *s++ = '\0';
  1843. X    return c;
  1844. X}
  1845. X
  1846. XComp parsecompsw() /**/
  1847. X{
  1848. XComp c1,c2,c3;
  1849. X
  1850. X    c1 = parsecomp();
  1851. X    if (!c1)
  1852. X        return NULL;
  1853. X    if (*pptr == Bar)
  1854. X        {
  1855. X        c2 = (Comp) alloc(sizeof *c2);
  1856. X        pptr++;
  1857. X        c3 = parsecompsw();
  1858. X        if (!c3)
  1859. X            return NULL;
  1860. X        c2->str = strdup("");
  1861. X        c2->left = c1;
  1862. X        c2->right = c3;
  1863. X        return c2;
  1864. X        }
  1865. X    return c1;
  1866. X}
  1867. X
  1868. X/* tokenize and see if ss matches tt */
  1869. X
  1870. Xint patmatch(ss,tt) /**/
  1871. Xchar *ss;char *tt;
  1872. X{
  1873. Xchar *s = ss,*t;
  1874. X
  1875. X    for (; *s; s++)
  1876. X        if (*s == '\\')
  1877. X            chuck(s);
  1878. X        else
  1879. X            for (t = ztokens; *t; t++)
  1880. X                if (*t == *s)
  1881. X                    {
  1882. X                    *s = (t-ztokens)+Pound;
  1883. X                    break;
  1884. X                    }
  1885. X    return matchpat(ss,tt);
  1886. X}
  1887. X
  1888. X/* remove unnecessary Nulargs */
  1889. X
  1890. Xvoid remnulargs(s) /**/
  1891. Xchar *s;
  1892. X{
  1893. Xint nl = *s;
  1894. Xchar *t = s;
  1895. X
  1896. X    while (*s)
  1897. X        if (*s == Nularg)
  1898. X            chuck(s);
  1899. X        else
  1900. X            s++;
  1901. X    if (!*t && nl)
  1902. X        {
  1903. X        t[0] = Nularg;
  1904. X        t[1] = '\0';
  1905. X        }
  1906. X}
  1907. X
  1908. X/* qualifier functions */
  1909. X
  1910. Xint qualdev(buf,dv) /**/
  1911. Xstruct stat *buf;long dv;
  1912. X{
  1913. X    return buf->st_dev == dv;
  1914. X}
  1915. X
  1916. Xint qualnlink(buf,ct) /**/
  1917. Xstruct stat *buf;long ct;
  1918. X{
  1919. X    return buf->st_nlink == ct;
  1920. X}
  1921. X
  1922. Xint qualuid(buf,uid) /**/
  1923. Xstruct stat *buf;long uid;
  1924. X{
  1925. X    return buf->st_uid == uid;
  1926. X}
  1927. X
  1928. Xint qualgid(buf,gid) /**/
  1929. Xstruct stat *buf;long gid;
  1930. X{
  1931. X    return buf->st_gid == gid;
  1932. X}
  1933. X
  1934. Xint qualisdev(buf,junk) /**/
  1935. Xstruct stat *buf;long junk;
  1936. X{
  1937. X    junk = buf->st_mode & S_IFMT;
  1938. X    return junk == S_IFBLK || junk == S_IFCHR;
  1939. X}
  1940. X
  1941. Xint qualmode(buf,mod) /**/
  1942. Xstruct stat *buf;long mod;
  1943. X{
  1944. X    return (buf->st_mode & S_IFMT) == mod;
  1945. X}
  1946. X
  1947. Xint qualflags(buf,mod) /**/
  1948. Xstruct stat *buf;long mod;
  1949. X{
  1950. X    return buf->st_mode & mod;
  1951. X}
  1952. X
  1953. Xint qualiscom(buf,mod) /**/
  1954. Xstruct stat *buf;long mod;
  1955. X{
  1956. X    return (buf->st_mode & (S_IFMT|S_IEXEC)) == (S_IFREG|S_IEXEC);
  1957. X}
  1958. X
  1959. SHAR_EOF
  1960. chmod 0644 zsh2.2/src/glob.c ||
  1961. echo 'restore of zsh2.2/src/glob.c failed'
  1962. Wc_c="`wc -c < 'zsh2.2/src/glob.c'`"
  1963. test 24554 -eq "$Wc_c" ||
  1964.     echo 'zsh2.2/src/glob.c: original size 24554, current size' "$Wc_c"
  1965. rm -f _shar_wnt_.tmp
  1966. fi
  1967. # ============= zsh2.2/src/hist.c ==============
  1968. if test -f 'zsh2.2/src/hist.c' -a X"$1" != X"-c"; then
  1969.     echo 'x - skipping zsh2.2/src/hist.c (File already exists)'
  1970.     rm -f _shar_wnt_.tmp
  1971. else
  1972. > _shar_wnt_.tmp
  1973. echo 'x - extracting zsh2.2/src/hist.c (Text)'
  1974. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/hist.c' &&
  1975. X/*
  1976. X *
  1977. X * hist.c - history expansion
  1978. X *
  1979. X * This file is part of zsh, the Z shell.
  1980. X *
  1981. X * This software is Copyright 1992 by Paul Falstad
  1982. X *
  1983. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  1984. X * use this software as long as: there is no monetary profit gained
  1985. X * specifically from the use or reproduction of this software, it is not
  1986. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  1987. X * included prominently in any copy made. 
  1988. X *
  1989. X * The author make no claims as to the fitness or correctness of this software
  1990. X * for any use whatsoever, and it is provided as is. Any use of this software
  1991. X * is at the user's own risk. 
  1992. X *
  1993. X */
  1994. X
  1995. X#include "zsh.h"
  1996. X
  1997. X#define HEAPSIZE 4096
  1998. X
  1999. Xstruct hp {
  2000. X    Hp next;
  2001. X    char *pool,*ptr;
  2002. X    int free,histno;
  2003. X};
  2004. X
  2005. Xstatic Hp hp_lit, hp_lex;
  2006. Xstatic Histent curhistent;
  2007. X
  2008. Xstatic int lastc;
  2009. X
  2010. X/* add a character to the current history word */
  2011. X
  2012. Xvoid hwaddc(c) /**/
  2013. Xint c;
  2014. X{
  2015. X    if (hlastw && hline && (!(errflag || lexstop) || c == HISTSPACE)) {
  2016. X        if (c == '!' && unset(NOBANGHIST)) hwaddc('\\');
  2017. X        *hptr++ = c;
  2018. X        if (hptr-hline >= hlinesz) {
  2019. X            int ll,flag = 0,oldsiz = hlinesz;
  2020. X
  2021. X            ll = hptr-hlastw;
  2022. X            if (curhistent->lex == hline) flag = 1;
  2023. X            hline = hp_realloc(&hp_lex,hline,oldsiz,hlinesz = oldsiz+16);
  2024. X            if (flag) curhistent->lex = hline;
  2025. X            hptr = hline+oldsiz;
  2026. X            hlastw = hptr-ll;
  2027. X        }
  2028. X    }
  2029. X}
  2030. X
  2031. X#define habort() { errflag = lexstop = 1; return ' '; }
  2032. X
  2033. X/* get a character after performing history substitution */
  2034. X
  2035. Xint hgetc() /**/
  2036. X{
  2037. Xint c,ev,farg,larg,argc,marg = -1,cflag = 0,bflag = 0;
  2038. Xchar buf[256],*ptr;
  2039. Xchar *sline,*eline;
  2040. X
  2041. Xtailrec:
  2042. X    c = hgetch();
  2043. X    if (stophist || alstackind)
  2044. X        {
  2045. X        hwaddc(c);
  2046. X        return c;
  2047. X        }
  2048. X    if (isfirstch && c == hatchar)
  2049. X        {
  2050. X        isfirstch = 0;
  2051. X        hungetch(hatchar);
  2052. X        hungets(":s");
  2053. X        c = bangchar;
  2054. X        goto hatskip;
  2055. X        }
  2056. X    if (c != ' ')
  2057. X        isfirstch = 0;
  2058. X    if (c == '\\') {
  2059. X        int g = hgetch();
  2060. X        
  2061. X        if (g != bangchar)
  2062. X            hungetch(g);
  2063. X        else {
  2064. X            hwaddc(bangchar);
  2065. X            return bangchar;
  2066. X        }
  2067. X    }
  2068. X    if (c != bangchar)
  2069. X        {
  2070. X        hwaddc(c);
  2071. X        return c;
  2072. X        }
  2073. Xhatskip:
  2074. X    *hptr = '\0';
  2075. X    if ((c = hgetch()) == '{')
  2076. X        {
  2077. X        bflag = cflag = 1;
  2078. X        c = hgetch();
  2079. X        }
  2080. X    if (c == '\"')
  2081. X        {
  2082. X        stophist = 1;
  2083. X        goto tailrec;
  2084. X        }
  2085. X    if (!cflag && inblank(c) || c == '=' || c == '(' || lexstop)
  2086. X        {
  2087. X        if (lexstop)
  2088. X            lexstop = 0;
  2089. X        else
  2090. X            hungetch(c);
  2091. X        hwaddc(bangchar);
  2092. X        return bangchar;
  2093. X        }
  2094. X    cflag = 0;
  2095. X    ptr = buf;
  2096. X
  2097. X    /* get event number */
  2098. X
  2099. X    if (c == '?')
  2100. X        {
  2101. X        for(;;)
  2102. X            {
  2103. X            c = hgetch();
  2104. X            if (c == '?' || c == '\n' || lexstop)
  2105. X                break;
  2106. X            else
  2107. X                *ptr++ = c;
  2108. X            }
  2109. X        if (c != '\n' && !lexstop)
  2110. X            c = hgetch();
  2111. X        *ptr = '\0';
  2112. X        ev = hconsearch(hsubl = ztrdup(buf),&marg);
  2113. X        if (ev == -1)
  2114. X            {
  2115. X            herrflush();
  2116. X            zerr("no such event: %s",buf,0);
  2117. X            habort();
  2118. X            }
  2119. X        }
  2120. X    else
  2121. X        {
  2122. X        int t0;
  2123. X        for (;;)
  2124. X            {
  2125. X            if (inblank(c) || c == ';' || c == ':' || c == '^' || c == '$' ||
  2126. X                    c == '*' || c == '%' || c == '}' || lexstop)
  2127. X                break;
  2128. X            if (ptr != buf) {
  2129. X                if (c == '-') break;
  2130. X                if ((idigit(buf[0]) || buf[0] == '-') && !idigit(c)) break;
  2131. X            }
  2132. X            *ptr++ = c;
  2133. X            if (c == '#' || c == bangchar)
  2134. X                {
  2135. X                c = hgetch();
  2136. X                break;
  2137. X                }
  2138. X            c = hgetch();
  2139. X            }
  2140. X        *ptr = 0;
  2141. X        if (!*buf)
  2142. X            ev = defev;
  2143. X        else if (t0 = atoi(buf))
  2144. X            ev = (t0 < 0) ? curhist+t0 : t0;
  2145. X        else if (*buf == bangchar)
  2146. X            ev = curhist-1;
  2147. X        else if (*buf == '#')
  2148. X            ev = curhist;
  2149. X        else if ((ev = hcomsearch(buf)) == -1)
  2150. X            {
  2151. X            zerr("event not found: %s",buf,0);
  2152. X            while (c != '\n' && !lexstop)
  2153. X                c = hgetch();
  2154. X            habort();
  2155. X            }
  2156. X        }
  2157. X
  2158. X    /* get the event */
  2159. X
  2160. X    if (!(eline = getevent(defev = ev)))
  2161. X        habort();
  2162. X
  2163. X    /* extract the relevant arguments */
  2164. X
  2165. X    argc = getargc(eline);
  2166. X    if (c == ':')
  2167. X        {
  2168. X        cflag = 1;
  2169. X        c = hgetch();
  2170. X        }
  2171. X    if (c == '*')
  2172. X        {
  2173. X        farg = 1;
  2174. X        larg = argc;
  2175. X        cflag = 0;
  2176. X        }
  2177. X    else
  2178. X        {
  2179. X        hungetch(c);
  2180. X        larg = farg = getargspec(argc,marg);
  2181. X        if (larg == -2)
  2182. X            habort();
  2183. X        if (farg != -1)
  2184. X            cflag = 0;
  2185. X        c = hgetch();
  2186. X        if (c == '*')
  2187. X            {
  2188. X            cflag = 0;
  2189. X            larg = argc;
  2190. X            }
  2191. X        else if (c == '-')
  2192. X            {
  2193. X            cflag = 0;
  2194. X            larg = getargspec(argc,marg);
  2195. X            if (larg == -2)
  2196. X                habort();
  2197. X            if (larg == -1)
  2198. X                larg = argc-1;
  2199. X            }
  2200. X        else
  2201. X            hungetch(c);
  2202. X        }
  2203. X    if (farg == -1)
  2204. X        farg = 0;
  2205. X    if (larg == -1)
  2206. X        larg = argc;
  2207. X    if (!(sline = getargs(eline,farg,larg)))
  2208. X        habort();
  2209. X
  2210. X    /* do the modifiers */
  2211. X
  2212. X    for(;;)
  2213. X        {
  2214. X        c = (cflag) ? ':' : hgetch();
  2215. X        cflag = 0;
  2216. X        if (c == ':')
  2217. X            {
  2218. X            int gbal = 0;
  2219. X        
  2220. X            if ((c = hgetch()) == 'g')
  2221. X                {
  2222. X                gbal = 1;
  2223. X                c = hgetch();
  2224. X                }
  2225. X            switch(c)
  2226. X                {
  2227. X                case 'p':
  2228. X                    histdone = HISTFLAG_DONE|HISTFLAG_NOEXEC;
  2229. X                    break;
  2230. X                case 'h':
  2231. X                    if (!remtpath(&sline))
  2232. X                        {
  2233. X                        herrflush();
  2234. X                        zerr("modifier failed: h",NULL,0);
  2235. X                        habort();
  2236. X                        }
  2237. X                    break;
  2238. X                case 'e':
  2239. X                    if (!rembutext(&sline))
  2240. X                        {
  2241. X                        herrflush();
  2242. X                        zerr("modifier failed: e",NULL,0);
  2243. X                        habort();
  2244. X                        }
  2245. X                    break;
  2246. X                case 'r':
  2247. X                    if (!remtext(&sline))
  2248. X                        {
  2249. X                        herrflush();
  2250. X                        zerr("modifier failed: r",NULL,0);
  2251. X                        habort();
  2252. X                        }
  2253. X                    break;
  2254. X                case 't':
  2255. X                    if (!remlpaths(&sline))
  2256. X                        {
  2257. X                        herrflush();
  2258. X                        zerr("modifier failed: t",NULL,0);
  2259. X                        habort();
  2260. X                        }
  2261. X                    break;
  2262. X                case 's':
  2263. X                    {
  2264. X                    int del;
  2265. X                    char *ptr1,*ptr2;
  2266. X                
  2267. X                    del = hgetch();
  2268. X                    ptr1 = hdynread2(del);
  2269. X                    if (!ptr1)
  2270. X                        habort();
  2271. X                    ptr2 = hdynread2(del);
  2272. X                    if (strlen(ptr1))
  2273. X                        {
  2274. X                        if (hsubl)
  2275. X                            free(hsubl);
  2276. X                        hsubl = ptr1;
  2277. X                        }
  2278. X                    if (hsubr)
  2279. X                        free(hsubr);
  2280. X                    hsubr = ptr2;
  2281. X                    }
  2282. X                case '&':
  2283. X                    if (hsubl && hsubr)
  2284. X                        subst(&sline,hsubl,hsubr,gbal);
  2285. X                    else
  2286. X                        {
  2287. X                        herrflush();
  2288. X                        zerr("no previous substitution with &",NULL,0);
  2289. X                        habort();
  2290. X                        }
  2291. X                    break;
  2292. X                case 'q':
  2293. X                    quote(&sline);
  2294. X                    break;
  2295. X                case 'x':
  2296. X                    quotebreak(&sline);
  2297. X                    break;
  2298. X                case 'l':
  2299. X                    downcase(&sline);
  2300. X                    break;
  2301. X                case 'u':
  2302. X                    upcase(&sline);
  2303. X                    break;
  2304. X                default:
  2305. X                    herrflush();
  2306. X                    zerr("illegal modifier: %c",NULL,c);
  2307. X                habort();
  2308. X                break;
  2309. X            }
  2310. X        }
  2311. X    else
  2312. X        {
  2313. X        if (c != '}' || !bflag)
  2314. X            hungetch(c);
  2315. X        if (c != '}' && bflag)
  2316. X            {
  2317. X            zerr("'}' expected",NULL,0);
  2318. X            habort();
  2319. X            }
  2320. X        break;
  2321. X        }
  2322. X    }
  2323. X
  2324. X    /* stuff the resulting string in the input queue and start over */
  2325. X
  2326. X    lexstop = 0;
  2327. X    if (alstackind != MAXAL)
  2328. X        {
  2329. X        hungets(HISTMARK);
  2330. X        alstack[alstackind++] = NULL;
  2331. X        }
  2332. X    for (ptr = sline; *ptr; ptr++) {
  2333. X        if (ptr[0] == '\\' && ptr[1] == '!') chuck(ptr);
  2334. X    }
  2335. X    hungets(sline);
  2336. X    histdone |= HISTFLAG_DONE;
  2337. X    if (isset(HISTVERIFY)) histdone |= HISTFLAG_NOEXEC|HISTFLAG_RECALL;
  2338. X    goto tailrec;
  2339. X}
  2340. X
  2341. X/* reset the alias stack for lexrestore () */
  2342. X
  2343. Xvoid clearalstack() /**/
  2344. X{
  2345. XAlias ix;
  2346. X
  2347. X    while (alstackind)
  2348. X        {
  2349. X        ix = alstack[--alstackind];
  2350. X        ix->inuse = 0;
  2351. X        }
  2352. X}
  2353. X
  2354. X/* get a character without history expansion */
  2355. X
  2356. Xint hgetch() /**/
  2357. X{
  2358. Xunsigned char *line,*pmpt,*pmpt2 = NULL;
  2359. Xint plen;
  2360. X
  2361. Xstart:
  2362. X    if (inbufct)
  2363. X        {
  2364. X        inbufct--;
  2365. X        if ((lastc = *inbufptr++) == ALPOP)
  2366. X            {
  2367. X            Alias ix;
  2368. X            char *t;
  2369. X
  2370. X            if (!alstackind)
  2371. X                {
  2372. X                zerr("alias stack underflow",NULL,0);
  2373. X                errflag = lexstop = 1;
  2374. X                return lastc = ' ';
  2375. X                }
  2376. X            ix = alstack[--alstackind];
  2377. X            if (ix)
  2378. X                {
  2379. X                ix->inuse = 0;
  2380. X                t = ix->text;
  2381. X                if (*t && t[strlen(t)-1] == ' ')
  2382. X                    alstat = ALSTAT_MORE;
  2383. X                else
  2384. X                    alstat = ALSTAT_JUNK;
  2385. X                }
  2386. X            goto start;
  2387. X            }
  2388. X        if (itok(lastc))
  2389. X            goto start;
  2390. X        return lastc;
  2391. X        }
  2392. X    if (strin || errflag)
  2393. X        {
  2394. X        lexstop = 1;
  2395. X        return lastc = ' ';
  2396. X        }
  2397. X    if (interact && isset(SHINSTDIN))
  2398. X        if (!isfirstln)
  2399. X            pmpt = (unsigned char *)putprompt(prompt2,&plen);
  2400. X        else
  2401. X            {
  2402. X            int foo;
  2403. X
  2404. X            pmpt = (unsigned char *)putprompt(prompt,&plen);
  2405. X            pmpt2 = (unsigned char *)((rprompt) ? putprompt(rprompt,&foo) : NULL);
  2406. X            }
  2407. X    if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) {
  2408. X        char *lbuf;
  2409. X        if (interact && isset(SHINSTDIN))
  2410. X            write(2,pmpt,strlen((char *) pmpt));
  2411. X        line = (unsigned char *)fgets(lbuf = zalloc(256),256,bshin);
  2412. X        if (!line) free(lbuf);
  2413. X    } else
  2414. X        line = zleread(pmpt,pmpt2,plen);
  2415. X    if (!line) {
  2416. X        lexstop = 1;
  2417. X        return lastc = ' ';
  2418. X    }
  2419. X    if (errflag) {
  2420. X        free(line);
  2421. X        lexstop = errflag = 1;
  2422. X        return lastc = ' ';
  2423. X    }
  2424. X    if (interact && isset(SHINSTDIN)) {
  2425. X        char *s = curhistent->lit;
  2426. X        curhistent->lit = hp_concat(s,(char*)line);
  2427. X    }
  2428. X    if (isfirstln) spaceflag = *line == ' ';
  2429. X    if (isset(VERBOSE)) {
  2430. X        fputs((char *) line,stderr);
  2431. X        fflush(stderr);
  2432. X    }
  2433. X    if (*line && line[strlen((char *) line)-1] == '\n')
  2434. X        {
  2435. X        lineno++;
  2436. X        if (interact && isset(SUNKEYBOARDHACK) && isset(SHINSTDIN) && 
  2437. X                SHTTY != -1 && *line && line[1] &&
  2438. X                line[strlen((char *) line)-2] == '`')
  2439. X            {
  2440. X            int ct;
  2441. X            unsigned char *ptr;
  2442. X
  2443. X            for (ct = 0, ptr = line; *ptr; ptr++)
  2444. X                if (*ptr == '`')
  2445. X                    ct++;
  2446. X            if (ct & 1)
  2447. X                {
  2448. X                ptr[-2] = '\n';
  2449. X                ptr[-1] = '\0';
  2450. X                }
  2451. X            }
  2452. X        }
  2453. X    isfirstch = 1;
  2454. X    hungets((char*)line);
  2455. X    free(line);
  2456. X    goto start;
  2457. X}
  2458. X
  2459. X/* Read one line of at most n-1 chars from the input queue */
  2460. X
  2461. Xchar *hgets(buf, n) /**/
  2462. Xchar *buf;int n;
  2463. X{
  2464. Xint l;
  2465. X
  2466. X    for (l = 0; l < n-1; l++)
  2467. X        if ((buf[l] = hgetch()) == '\n' || lexstop)
  2468. X            break;
  2469. X    buf[l+(lexstop?0:1)] = 0;
  2470. X
  2471. X    return (!lexstop || l) ? buf : NULL;
  2472. X}
  2473. X
  2474. X/* put a string in the input queue */
  2475. X
  2476. Xvoid hungets(str) /**/
  2477. Xchar *str;
  2478. X{
  2479. Xint slen = strlen(str);
  2480. X
  2481. X/* shrink inbuf if it gets too big */
  2482. X
  2483. X    if (!inbufct && inbufsz > 65536)
  2484. X        {
  2485. X        free(inbuf);
  2486. X        inbuf = zalloc(inbufsz = 256);
  2487. X        inbufptr = inbuf+inbufsz;
  2488. X        inbufct = 0;
  2489. X        }
  2490. X    if (slen+inbufct > inbufsz)
  2491. X        {
  2492. X        char *x;
  2493. X
  2494. X        while (slen+inbufct > inbufsz)
  2495. X            inbufsz *= 4;
  2496. X        x = zalloc(inbufsz);
  2497. X        memcpy(x+inbufsz-inbufct,inbufptr,inbufct);
  2498. X        inbufptr = x+inbufsz-inbufct;
  2499. X        free(inbuf);
  2500. X        inbuf = x;
  2501. X        }
  2502. X    memcpy(inbufptr -= slen,str,slen);
  2503. X    inbufct += slen;
  2504. X}
  2505. X
  2506. X/* unget a char and remove it from hline */
  2507. X
  2508. Xvoid hungetc(c) /**/
  2509. Xint c;
  2510. X{
  2511. X    if (lexstop)
  2512. X        return;
  2513. X    if (hlastw) {
  2514. SHAR_EOF
  2515. true || echo 'restore of zsh2.2/src/hist.c failed'
  2516. fi
  2517. echo 'End of zsh2.2 part 8'
  2518. echo 'File zsh2.2/src/hist.c is continued in part 9'
  2519. echo 9 > _shar_seq_.tmp
  2520. exit 0
  2521.  
  2522. exit 0 # Just in case...
  2523.